package com.common.client.usermanager;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;

import com.common.shared.LSystem;
import com.common.shared.Language;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Cookies;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.VisibilityChangedEvent;
import com.smartgwt.client.widgets.events.VisibilityChangedHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.PasswordItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.KeyDownEvent;
import com.smartgwt.client.widgets.form.fields.events.KeyDownHandler;
import com.smartgwt.client.widgets.layout.VLayout;

public class WLoginForm extends Window {

	private static final String USERNAME = "USERNAME";
	private static final String LANGUAGE = "LANGUAGE";
	private static final String SYSTEM = "SYSTEM";

	private TextItem user_nameField;
	private PasswordItem pwdField;
	private SelectItem languageItem;
	private SelectItem systemItem;
	private LogOnHandler logOnHandler;

	private Date expireTime;

	public WLoginForm(ArrayList<Language> languages,
			ArrayList<LSystem> systems, LogOnHandler logOnHandler) {

		super();
		this.logOnHandler = logOnHandler;
		expireTime = new Date();
		long time = expireTime.getTime();
		time = time + (1000 * 60 * 60 * 24 * 14);// seven days
		expireTime.setTime(time);
		this.setTitle("Login");
		this.setAutoSize(true);
		this.setIsModal(true);
		this.setShowMinimizeButton(false);
		this.setShowCloseButton(false);
		this.setIsModal(true);
		this.setShowModalMask(true);

		DynamicForm form = new DynamicForm();

		ArrayList<FormItem> formItems = new ArrayList<FormItem>();
		user_nameField = new TextItem("username", "User Name");
		user_nameField.setWidth(220);
		user_nameField.setWrapTitle(false);
		formItems.add(user_nameField);

		user_nameField.setValue(getCookies());
		pwdField = new PasswordItem("pwd", "Password");
		pwdField.setWidth(220);
		formItems.add(pwdField);
		KeyDownHandler kdH = new KeyDownHandler() {

			@Override
			public void onKeyDown(KeyDownEvent event) {
				if (event.getKeyName().equals("Enter"))
					login();

			}
		};
		user_nameField.addKeyDownHandler(kdH);
		pwdField.addKeyDownHandler(kdH);

		if (!(languages == null || languages.size() == 0)) {
			LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
			for (Language language : languages) {
				valueMap.put(language.getId() + "", language.getLanguage_name());
			}
			languageItem = new SelectItem("language", "Language");
			languageItem.setWidth(220);
			languageItem.setValueMap(valueMap);
			String slang = getLanguage() + "";
			if (!valueMap.containsKey(slang))
				slang = valueMap.keySet().iterator().next();
			languageItem.setValue(slang);
			languageItem.addKeyDownHandler(kdH);
			formItems.add(languageItem);
		}
		if (!(systems == null || systems.size() == 0)) {
			LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
			for (LSystem system : systems) {
				valueMap.put(system.getId() + "", system.getSystem_name());
			}
			systemItem = new SelectItem("system", "System");
			systemItem.setWidth(220);
			systemItem.setValueMap(valueMap);
			String slang = getSystem() + "";
			if (!valueMap.containsKey(slang))
				slang = valueMap.keySet().iterator().next();
			systemItem.setValue(slang);
			systemItem.addKeyDownHandler(kdH);
			formItems.add(systemItem);
		}

		form.setFields(formItems.toArray(new FormItem[] {}));
		VLayout layout = new VLayout(10);
		layout.addMember(form);
		IButton bLogin = new IButton("Login", new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				login();
			}
		});
		layout.addMember(bLogin);
		layout.draw();
		this.addItem(layout);
		this.setAutoCenter(true);

		addVisibilityChangedHandler(new VisibilityChangedHandler() {

			@Override
			public void onVisibilityChanged(VisibilityChangedEvent event) {
				if (event.getIsVisible()) {

					WLoginForm.this.centerInPage();
				}

			}
		});

	}

	public WLoginForm(ArrayList<Language> languages, LogOnHandler logOnHandler) {
		this(languages, null, logOnHandler);
	}

	private void login() {
		if (logOnHandler != null) {
			String username = getNonNullFieldValue(user_nameField);
			String password = getNonNullFieldValue(pwdField);
			int language = Integer.parseInt(getNonNullFieldValue(languageItem,
					"0"));
			int system = Integer
					.parseInt(getNonNullFieldValue(systemItem, "0"));
			logOnHandler.onLogOn(new LogOnEvent(username, password, language,
					system, this));
		}
	}

	private String getNonNullFieldValue(FormItem formItem, String defaultVal) {
		Object val = formItem == null ? defaultVal : formItem.getValue();
		return val == null ? defaultVal : val.toString().trim();
	}

	private String getNonNullFieldValue(FormItem formItem) {
		return getNonNullFieldValue(formItem, "");
	}

	public final static int ERRFIELD_UN = 1;
	public final static int ERRFIELD_PASS = 2;
	public final static int ERRFIELD_LAN = 3;
	public final static int ERRFIELD_SYSTEM = 4;

	public void setError(Throwable err, final int field) {
		SC.say(err.getMessage(), new BooleanCallback() {

			@Override
			public void execute(Boolean value) {
				FormItem formItem = null;
				switch (field) {
				case ERRFIELD_UN:
					formItem = user_nameField;
					break;
				case ERRFIELD_PASS:
					formItem = pwdField;
					break;
				case ERRFIELD_LAN:
					formItem = languageItem;
					break;
				case ERRFIELD_SYSTEM:
					formItem = systemItem;
					break;

				default:
					break;
				}
				if (formItem != null) {
					formItem.focusInItem();
				}

			}
		});
	}

	public interface LogOnHandler {
		public void onLogOn(LogOnEvent logOnEvent);
	}

	public class LogOnEvent {
		private String username;
		private String password;
		private int language;
		private int system;
		private WLoginForm loginForm;

		public LogOnEvent(String username, String password, int language,
				int system, WLoginForm loginForm) {
			setUsername(username);
			setPassword(password);
			setLanguage(language);
			setLoginForm(loginForm);
			setSystem(system);
		}

		public String getUsername() {
			return username;
		}

		private void setUsername(String username) {
			this.username = username;
		}

		public String getPassword() {
			return password;
		}

		private void setPassword(String password) {
			this.password = password;
		}

		public int getLanguage() {
			return language;
		}

		private void setLanguage(int language) {
			this.language = language;
		}

		public WLoginForm getLoginForm() {
			return loginForm;
		}

		private void setLoginForm(WLoginForm loginForm) {
			this.loginForm = loginForm;
		}

		public int getSystem() {
			return system;
		}

		public void setSystem(int system) {
			this.system = system;
		}

	}

	public void done() {
		saveCookiesUserName(user_nameField.getValueAsString());
		if (languageItem != null) {
			try {
				saveCookiesLanguage(Integer.parseInt(languageItem.getValue()
						.toString()));
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		if (systemItem != null) {
			try {
				saveCookiesSystem(Integer.parseInt(systemItem.getValue()
						.toString()));
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		destroy();
	}

	private String getCookies() {
		String username = GWT.getModuleName() + USERNAME;
		return Cookies.getCookie(username);
	}

	private int getLanguage() {
		String slanguage = GWT.getModuleName() + LANGUAGE;
		slanguage = Cookies.getCookie(slanguage);
		try {
			return Integer.parseInt(slanguage);
		} catch (Exception e) {
			return -1;
		}
	}

	private int getSystem() {
		String sSystem = GWT.getModuleName() + SYSTEM;
		sSystem = Cookies.getCookie(sSystem);
		try {
			return Integer.parseInt(sSystem);
		} catch (Exception e) {
			return -1;
		}
	}

	private void saveCookiesUserName(String username) {
		String susername = GWT.getModuleName() + USERNAME;
		Cookies.setCookie(susername, username, expireTime);
	}

	private void saveCookiesLanguage(int language) {
		String slanguage = GWT.getModuleName() + LANGUAGE;
		Cookies.setCookie(slanguage, language + "", expireTime);
	}

	private void saveCookiesSystem(int system) {
		String slanguage = GWT.getModuleName() + SYSTEM;
		Cookies.setCookie(slanguage, system + "", expireTime);
	}

	@Override
	public void show() {
		super.show();
		if (user_nameField.getValue() != null
				&& user_nameField.getValue().toString().trim() != "")
			pwdField.focusInItem();
		else
			user_nameField.focusInItem();
	}
}
